package com.ehome.poct.core.service.pay;

import com.ehome.paymentcenter.api.pay.BasePayReqCO;
import com.ehome.poct.core.api.constant.enums.ScanTypeEnums;
import com.ehome.poct.core.api.dto.order.UnificationPayReqDTO;
import com.ehome.poct.core.api.vo.order.PayChannelRespVO;
import com.ehome.poct.core.constant.PayBizCodeEnums;
import com.ehome.poct.core.utils.EHomeAssert;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * @auther: kuiba.peng
 * @date: 2022/10/28 12:52
 * @description:
 */
@SuppressWarnings("rawtypes")
@Component("PayFactory")
public class PayFactory {

    private final static Map<ScanTypeEnums, AbstractPayStrategy> PAY_STRATEGY_MAP = new ConcurrentHashMap<>();

    private final List<AbstractPayStrategy> payStrategyList;


    public PayFactory(@Autowired List<AbstractPayStrategy> payStrategyList) {
        this.payStrategyList = payStrategyList;
        Map<ScanTypeEnums, AbstractPayStrategy> payStrategyMap = payStrategyList.stream().collect(Collectors.toMap(AbstractPayStrategy::getSupportType, payStrategy -> payStrategy, (o1, o2) -> o1));
        PAY_STRATEGY_MAP.putAll(payStrategyMap);
    }

    public AbstractPayStrategy getPayStrategy(BasePayReqCO basePayReqCO) {
        Optional<AbstractPayStrategy> optional = payStrategyList.stream()
                .filter(abstractPayStrategy -> abstractPayStrategy.supports(basePayReqCO))
                .findFirst();
        EHomeAssert.isTrue(optional.isPresent(), PayBizCodeEnums.UNKNOWN_PAY_TYPE);
        return optional.get();
    }

    public AbstractPayStrategy getPayStrategy(ScanTypeEnums scanType) {
        AbstractPayStrategy payStrategy = PAY_STRATEGY_MAP.get(scanType);
        EHomeAssert.isTrue(Objects.nonNull(payStrategy), PayBizCodeEnums.UNKNOWN_PAY_TYPE);
        return payStrategy;
    }

    public PayChannelRespVO pay(ScanTypeEnums scanType, UnificationPayReqDTO payReqDTO) {
        return getPayStrategy(scanType).pay(payReqDTO);
    }
}
